package com.example.ad.sdk.domain.view

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.fragment.app.Fragment
import java.util.UUID
import java.util.concurrent.ConcurrentLinkedQueue

/**
 * BaseFragment 是一个抽象基类，用于封装 Fragment 的通用逻辑和功能。
 * 它提供了视图初始化、数据加载、生命周期管理以及加载等待框的显示和隐藏等功能。
 *
 * 主要功能包括：
 * 1. 提供布局文件 ID 的抽象方法 [layoutId]，子类必须实现以指定布局资源。
 * 2. 提供视图初始化方法 [initView]，子类可以在此方法中初始化视图组件。
 * 3. 提供数据加载方法 [initData]，支持懒加载（Lazy Load）和非懒加载两种模式。
 * 5. 支持 Fragment 生命周期事件监听器 [FragmentLifecycleEventObserver]，允许外部监听 Fragment 的显示/隐藏状态变化。
 * 6. 提供页面唯一标识符 [getPageId]，用于标识当前 Fragment 实例。
 * 7. 提供延迟执行任务的功能 [withLoaded]，确保任务在数据加载完成后执行。
 *
 * ### 关键属性
 * - [pageId]: 当前 Fragment 的唯一标识符，默认为 UUID。
 * - [isLoadData]: 标记是否已经加载过数据。
 * - [destroyView]: 标记视图是否已经被销毁。
 * - [fragmentLifecycleEventObservers]: 存储 Fragment 生命周期事件监听器的队列。
 * - [fragmentDataLoaders]: 存储需要在数据加载完成后执行的任务列表。
 *
 * ### 懒加载机制
 * - 默认开启懒加载（通过 [isLazyLoad] 方法控制），只有当 Fragment 被添加到 Activity 并且可见时才会加载数据。
 * - 如果懒加载关闭，则在 [onViewCreated] 方法中立即加载数据。
 *
 * ### 加载等待框
 * - [showLoading] 方法支持自定义加载提示信息、是否可取消、是否有阴影背景等参数。
 * - [dismissLoading] 方法用于隐藏加载等待框，并支持设置延迟关闭时间。
 *
 * ### 使用场景
 * - 适用于所有需要继承 Fragment 的模块化开发场景。
 * - 提供了统一的生命周期管理和数据加载逻辑，减少重复代码。
 */
abstract class BaseFragment : Fragment() {
    private var pageId: String? = null

    //是否第一次加载
    private var isLoadData: Boolean = false

    //是否销毁了view
    private var destroyView: Boolean = false

    private val fragmentLifecycleEventObservers = ConcurrentLinkedQueue<FragmentLifecycleEventObserver>()
    val fragmentDataLoaders = ArrayList<Runnable>()

    /**
     * 获取当前 Fragment 绑定的布局资源 ID。
     *
     * @return 布局资源 ID
     */
    abstract fun layoutId(): Int

    /**
     * 创建并返回当前 Fragment 的视图。
     *
     * @param inflater 用于实例化布局文件的 LayoutInflater 对象
     * @param container 父容器
     * @param savedInstanceState 保存的实例状态
     * @return 当前 Fragment 的根视图
     */
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(layoutId(), container, false)
    }

    /**
     * 初始化视图和数据。
     *
     * @param view 当前 Fragment 的根视图
     * @param savedInstanceState 保存的实例状态
     */
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initRenderers(savedInstanceState)
        if (!isLazyLoad()) {
            initData()
            isLoadData = true
        }
    }

    /**
     * 抽象方法，用于初始化渲染器或视图组件。
     * 子类必须实现此方法，以完成视图的初始化工作。
     * @param savedInstanceState 保存的实例状态
     */
    abstract fun initRenderers(savedInstanceState: Bundle?)

    /**
     * 初始化数据。
     */
    open fun initData() {}

    /**
     * 判断是否启用懒加载。
     *
     * @return 如果启用懒加载则返回 true，否则返回 false
     */
    open fun isLazyLoad(): Boolean = true



    /**
     * 当 Fragment 可见时调用的方法。
     */
    override fun onResume() {
        super.onResume()
        lazyLoadData()
    }

    /**
     * 当 Fragment 的隐藏状态发生变化时调用的方法。
     *
     * @param hidden 如果 Fragment 被隐藏，则为 true，否则为 false
     */
    @CallSuper
    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        fragmentLifecycleEventObservers.forEach {
            it.onHiddenChanged(hidden)
        }
    }

    /**
     * 懒加载数据。
     */
    private fun lazyLoadData() {
        if (!isAdded || isLoadData) {
            return
        }
        isLoadData = true
        initData()
        //加载完成后立即执行
        fragmentDataLoaders.forEach {
            it.run()
        }
        fragmentDataLoaders.clear()
    }

    /**
     * 判断是否已经加载过数据。
     *
     * @return 如果已经加载过数据则返回 true，否则返回 false
     */
    fun isLoadData(): Boolean {
        return isLoadData
    }

    /**
     * 当 Fragment 的视图被销毁时调用的方法。
     */
    override fun onDestroyView() {
        super.onDestroyView()
        destroyView = true
    }

    /**
     * 判断视图是否已经被销毁。
     *
     * @return 如果视图已经被销毁则返回 true，否则返回 false
     */
    fun isDestroyView(): Boolean {
        return destroyView
    }

    /**
     * 获取页面的唯一标识符。
     *
     * @return 页面的唯一标识符
     */
    fun getPageId(): String {
        val pageId = pageId
        if (pageId != null) {
            return pageId
        }
        return UUID.randomUUID().toString().replace("-", "").also {
            this.pageId = it
        }
    }

    /**
     * 添加 Fragment 生命周期事件观察者。
     *
     * @param observer 观察者
     */
    fun addFragmentLifecycleEventObserver(observer: FragmentLifecycleEventObserver) {
        fragmentLifecycleEventObservers.add(observer)
    }

    /**
     * 移除 Fragment 生命周期事件观察者。
     *
     * @param observer 观察者
     */
    fun removeFragmentLifecycleEventObserver(observer: FragmentLifecycleEventObserver) {
        fragmentLifecycleEventObservers.remove(observer)
    }

    /**
     * 在数据加载完成后执行指定的代码块。
     *
     * @param block 代码块
     */
    inline fun withLoaded(crossinline block: () -> Unit) {
        if (isLoadData()) {
            block()
        } else {
            fragmentDataLoaders.add(Runnable {
                block()
            })
        }
    }

    /**
     * 当 Fragment 被销毁时调用的方法。
     */
    override fun onDestroy() {
        super.onDestroy()
        fragmentLifecycleEventObservers.clear()
    }
}

/**
 * Fragment 生命周期事件观察者接口。
 */
fun interface FragmentLifecycleEventObserver {
    /**
     * 当 Fragment 的隐藏状态发生变化时调用的方法。
     *
     * @param hidden 如果 Fragment 被隐藏，则为 true，否则为 false
     */
    fun onHiddenChanged(hidden: Boolean)
}